
package hk.ces.oxfam.patch.result.xml;

import hk.ces.oxfam.patch.xml.factory.SQLResultXMLFactory;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.log4j.Logger;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;

/**
 *
 * @author ReutyCheng
 */
public abstract class AbstractXMLFactory<T extends XML> implements XMLFactory<T>
{  
  private final String folder;
  private final String fileName;
  private boolean overwrite = true;
  protected List<T> xmlItemList = new ArrayList<T>();

  protected AbstractXMLFactory(String fileName)
  {
    this(AbstractXMLFactory.class.getClassLoader().getResource("").getPath(), fileName);
  }

  protected AbstractXMLFactory(String folder, String fileName)
  {
    this.folder = folder;
    this.fileName = fileName.split("\\.")[0] + ".xml";
  }

  protected abstract Document getDocument();

  protected abstract String getXslFileName();

  public void setOverwrite(boolean overwrite)
  {
    this.overwrite = overwrite;
  }

  public void setXMLItems(T... xmlItems)
  {
    for (T xmlItem : xmlItems)
    {
      this.xmlItemList.add(xmlItem);
    }
  }

  public void writeToFile()
  {
    Document document = this.getDocument();
    Document originalDocument = null;
    try
    {
      File file = new File(folder + "\\" + fileName);
      if (file.exists() && !this.overwrite)
      {
        SAXReader reader = new SAXReader();
        originalDocument = reader.read(file);
        Element root = originalDocument.getRootElement();
        root.appendContent(document.getRootElement());
      }
      else
      {
        originalDocument = document;
      }
      FileOutputStream fos = new FileOutputStream(new File(folder + "\\" + fileName));
      OutputFormat format = OutputFormat.createPrettyPrint();
      format.setEncoding("UTF-8");
      XMLWriter writer = new XMLWriter(fos, format);
      writer.write(originalDocument);
      writer.close();

      String xslFileName = getXslFileName();
      if (xslFileName != null && xslFileName.length() > 1)
      {
        File xslCloneFile = new File(folder + "/" + xslFileName);
        if (!xslCloneFile.exists())
        {
          File xslOriginalFile = new File(SQLResultXMLFactory.class.getResource(xslFileName).getFile());

          FileInputStream inputStream = new FileInputStream(xslOriginalFile);
          FileOutputStream outputStream = new FileOutputStream(xslCloneFile);
          byte[] buffer = new byte[1024];
          int length = 0;

          while ((length = inputStream.read(buffer)) > 0)
          {
            outputStream.write(buffer, 0, length);
          }

          outputStream.close();
        }
      }

      Logger.getLogger(this.getClass()).debug("SQLResult XML File have wrote on [" + folder + "\\" + fileName + "]");
    }
    catch (DocumentException ex)
    {
      Logger.getLogger(this.getClass()).error(ex.getMessage(), ex);
    }
    catch (IOException ex)
    {
      Logger.getLogger(this.getClass()).error(ex.getMessage(), ex);
    }
  }

  protected Document addXMLStyleSheet(Document document)
  {
    Map instructions = new HashMap();
    instructions.put("type", "text/xsl");
    instructions.put("href", getXslFileName());

    return document.addProcessingInstruction("xml-stylesheet", instructions);
  }
}
